﻿#ifndef __MY_BACKUP__
#define __MY_BACKUP__
#include "Util.hpp"
#include "DataManager.hpp"
#include "httplib.h"
#include <sstream>
#include <Windows.h>//注意这个头文件要包含到httplib.h后面


namespace cloud
{
	#define SERVER_ADDR "47.120.76.102"
	#define SERVER_PORT 9090
	class Backup
	{
	private:
		std::string _back_dir;
		DataManager* _data;
	private:
		std::string GetFileIdentity(const std::string& filename)
		{
			FileUtil fu(filename);
			std::stringstream ss;
			ss << fu.FileName() << "-" << fu.FileSize() << "--" << fu.LastMTime();
			return ss.str();
		}
		bool Upload(const std::string& filename)
		{
			//1.获取文件内容
			FileUtil fu(filename);
			std::string body;
			fu.GetContent(&body);
			//2.搭建http客户端上传文件数据
			httplib::Client client(SERVER_ADDR, SERVER_PORT);
			httplib::MultipartFormData item;
			item.content = body;
			item.content_type = "application/octet-stream";
			item.filename = fu.FileName();
			item.name = "file";
			httplib::MultipartFormDataItems items;
			items.push_back(item);
			auto ret = client.Post("/upload", items);
			if (!ret || ret->status != 200)  return false;
			return true;
			
		}
		bool IsNeedUpload(const std::string& filename)
		{
			//如果是新增的文件或者文件已经被修改过则需要上传
			FileUtil fu(filename);
			std::string id;
			//判断文件是否存在
			if (_data->GetOneByFilename(filename, &id)!= false)
			{
				//判断文件是否被修改
				std::string new_id = GetFileIdentity(filename);
				if (id == new_id)
				{
					//文件存在并且没有被修改
					return false;
				}
			}
			//文件是新增或者已经被修改
			//还需要判断如果是大文件的话，它正在拷贝到这个目录，拷贝需要一个过程，所以文件会一直被修改，所以还需要再判断一下
			//最严谨的做法是判断有没有程序正在访问这个文件，我们这里采用的是根据最近访问时间来判断
			if (time(nullptr) - fu.LastMTime() < 3)
				return false;
			std::cout << filename << " need upload" << std::endl;
			return true;

		}
	public:
		Backup(const std::string& back_dir, const std::string& back_file) :_back_dir(back_dir)
		{
			_data = new DataManager(back_file);
		}
		void RunModule()
		{
			////测试获取文件唯一标识
			//while (1)
			//{
			//	//1.遍历整个备份目录，获取所有文件名
			//	FileUtil fu(_back_dir);
			//	std::vector<std::string> array;
			//	fu.ScanDirectory(&array);

			//	//2.加载所有文件备份信息
			//	for (auto& a : array)
			//	{
			//		std::string id = GetFileIdentity(a);
			//		_data->Insert(a, id);
			//	}
			//}

			while (true)
			{
				//1.遍历指定文件夹，获取所有文件名
				FileUtil fu(_back_dir);
				std::vector<std::string> array;
				fu.ScanDirectory(&array);
				//2.判断文件是否需要上传
				for (auto& a : array)
				{
					//3.上传文件
					if (IsNeedUpload(a) == false)
					{
						continue;
					}
					if (Upload(a) == true)
					{
						//增加文件备份信息
						_data->Insert(a, GetFileIdentity(a));
						std::cout << a << " upload success" << std::endl;
					}

				}
				Sleep(10);
			}
		}

	};
}
#endif